using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using Oplaco.Core.DAL.MembersDataComponentTableAdapters;
using System.Web.Profile;
using System.Xml;
using System.Collections.Generic;
using Oplaco.Core.Configuration;


namespace Oplaco.Core.BusinessLogicLayer
{
	/// <summary>
	/// Contains the implementation for the creation of users.
	/// </summary>
    public sealed class MembersDB : ProfileBase
    {
        private ProfileBase profileBase;

        #region Property       
        public Int32 MemberID
        {
            get;
            set;
        }
        public Guid UserID
        {
            get;
            set;
        }

        public Guid AvatarID
        {
            get;
            set;
        }

        public string Nickname
        {
            set;
            get;
        }

        public string Username
        {
            set;
            get;
        }

        public String Password
        {
            set;
            get;
        }

        public String Email
        {
            set;
            get;
        }

        public int TelephonePrefix
        {
            get;
            set;
        }

        public int Telephone
        {
            get;
            set;
        }

        public string TwitterToken
        {
            get;
            set;
        }

        public string TwitterSecret
        {
            get;
            set;
        }

        public GlobalInformationSystem GIS
        {
            set;
            get;
        }
        #endregion

        public MembersDB() { }

        public static int CreateMember(string username, string aspApplicationName)
        {
            DateTime dateCreated = DateTime.Now;

            // All users are added to Guests role upon registration.
            Roles.AddUserToRole(username, "Guests");

            using (MembersDataAdapter db = new MembersDataAdapter())
            {
                return (int)db.InsertMember(username, aspApplicationName, dateCreated);
            }
        }

        public void Initialize(int memberId) {

            
            if (memberId > 0)
            {
                using (MembersDataAdapter db = new MembersDataAdapter())
                {
                    Oplaco.Core.DAL.MembersDataComponent.MembersDataTable data = db.GetMemberById(memberId);
                    if (data.Count > 0)
                    {
                        
                        this.Username = data[0].AspNetUsername;
                        this.MemberID = memberId;
                        MembershipUser usr = Membership.GetUser(this.Username);
                        if (usr != null) {
                            this.profileBase = new ProfileBase();
                            this.profileBase.Initialize(this.Username, true);
                            GlobalInformationSystem gis = new GlobalInformationSystem();
                            this.Email = usr.Email;
                            this.Password = usr.GetPassword();
                            this.Nickname = (string)this.profileBase.GetPropertyValue("Nickname");
                            //this.TwitterSecret = (string)this.profileBase.GetPropertyValue("TwitterAccessSecret");
                            //this.TwitterToken = (string)this.profileBase.GetPropertyValue("TwitterAccessToken");
                            this.GIS = gis.Create(GisType.home, (Int32)this.profileBase.GetPropertyValue("ZipCode"), (String)this.profileBase.GetPropertyValue("ZipCodeExtension"), String.Empty);
                            
                        }

                    }
                }
            }

            
        }

        /// <summary>
        /// Basically an overloaded method for social network integration, where you cannot verify the user based on username & password
        /// </summary>
        /// <param name="username"></param>
        public void Initialize(string username) {
            
            if (String.IsNullOrEmpty(username)) throw new Oplaco.Exceptions.DataAccessLayerException("username param was empty");
            using (MembersDataAdapter db = new MembersDataAdapter())
            {
                Oplaco.Core.DAL.MembersDataComponent.MembersDataTable data = db.GetMemberByUsername(username, "/os.oplaco");
                if (data.Count > 0)
                {
                    this.MemberID = data[0].Id;
                    this.Username = data[0].AspNetUsername;
                    MembershipUser usr = Membership.GetUser(this.Username);
                    if (usr != null)
                    {
                        this.Username = username;
                        this.profileBase = new ProfileBase();
                        this.profileBase.Initialize(this.Username, true);
                        GlobalInformationSystem gis = new GlobalInformationSystem();
                        this.Email = usr.Email;
                        this.Password = usr.GetPassword();
                        this.Nickname = (string)this.profileBase.GetPropertyValue("Nickname");
                        // this.TwitterSecret = (string)this.profileBase.GetPropertyValue("TwitterAccessSecret");
                        //this.TwitterToken = (string)this.profileBase.GetPropertyValue("TwitterAccessToken");
                        this.GIS = gis.Create(GisType.home, (Int32)this.profileBase.GetPropertyValue("ZipCode"), (String)this.profileBase.GetPropertyValue("ZipCodeExtension"), String.Empty);

                    }
                }
            }
            
        }

        /// <summary>
        /// Create user in .Net membership tables and the oplaco sys tables
        /// </summary>
        /// <param name="username">emailaddresss</param>
        /// <param name="password"></param>
        /// <param name="postalcode">zipcode</param>
        /// <param name="postalcodeExt">zipcode extension</param>
        /// <returns></returns>
        public Int32 CreateUser(string username, string password)
        {
            try
            {
                                
                DateTime dateCreated = DateTime.Now;
                this.profileBase = new ProfileBase();
                
                //first handle membership
                Membership.CreateUser(username, password, username);
                
                //sync the membership database with system database
                using (MembersDataAdapter db = new MembersDataAdapter())
                {
                    this.MemberID = (int)db.InsertMember(username, Membership.ApplicationName, dateCreated);                     
                }
                         

                //now generate profile                
                this.profileBase.Initialize(username, true);
                this.profileBase.SetPropertyValue("MemberId", this.MemberID);
                this.profileBase.SetPropertyValue("Username", username);
                this.profileBase.SetPropertyValue("Password", password);
                this.profileBase.SetPropertyValue("Email", username);

                //add users to default role
                Roles.AddUsersToRole(new String[] { username }, "Users");

                //done, now fill
                this.Username = username;
                this.Nickname = username;
                this.Password = password;
                this.Email = username;

                //GIS - to be implemented
                //http://msdn.microsoft.com/en-us/magazine/dd434647.aspx
                //GlobalInformationSystem gis = new GlobalInformationSystem();
                //this.GIS = gis.Create(GisType.home, postalcode, postalcodeExt, String.Empty);

                this.profileBase.Save();

                MembershipUser usr = Membership.GetUser(username);
                Guid userKey = new Guid(usr.ProviderUserKey.ToString());
                this.UserID = userKey;

                return this.MemberID;
            }
            catch (Oplaco.Exceptions.DataAccessLayerException DLE)
            {
                Oplaco.Exceptions.AppService.ReplaceWithPresentationLayerException(DLE);
            }
            catch (MembershipCreateUserException MCUE)
            {
                throw MCUE;
            }
            catch (Exception exception)
            {
                Oplaco.Exceptions.AppService.ProcessAndNotifyPresentationLayerException(exception);
            }

            return 0;
        }

        public void UpdateProfile(string username, 
            string nickname, 
            string firstname, 
            string lastname, 
            string phonenumberprefix, 
            string phonenumber, 
            Int32 zipcode, 
            string zipcodeExt, 
            string AvatarUrl, 
            string twitterAccessToken, 
            string twitterAccessSecret, 
            string facebookKey, 
            string xboxLifeKey, 
            string deliciousKey)
        {

            try
            {
                profileBase = new ProfileBase();

                if (String.IsNullOrEmpty(nickname))
                {
                    char[] chars = new char[] { '@' };
                    string[] names = username.Split(chars);
                    nickname = names[0] + DateTime.Now.Millisecond;
                }

                this.profileBase.Initialize(username, true);
                this.profileBase.SetPropertyValue("Nickname", nickname);
                this.profileBase.SetPropertyValue("Firstname", firstname);
                this.profileBase.SetPropertyValue("Lastname", lastname);
                this.profileBase.SetPropertyValue("PhoneNumberPrefix", phonenumberprefix);
                this.profileBase.SetPropertyValue("PhoneNumber", phonenumber);
                this.profileBase.SetPropertyValue("ZipCode", zipcode);
                this.profileBase.SetPropertyValue("ZipCodeExtension", zipcodeExt);
                this.profileBase.SetPropertyValue("AvatarID", AvatarID.ToString());
                //this.profileBase.SetPropertyValue("TwitterAccessToken", twitterAccessToken);
                //this.profileBase.SetPropertyValue("TwitterAccessSecret", twitterAccessSecret);
                this.profileBase.SetPropertyValue("Facebook", facebookKey);
                this.profileBase.SetPropertyValue("XboxLife", xboxLifeKey);
                this.profileBase.SetPropertyValue("Delicious", deliciousKey);

                this.profileBase.Save();

            }
            catch (SettingsPropertyNotFoundException SPNFE) {

                Oplaco.Exceptions.AppService.ProcessAndNotifyBusinessLayerException(SPNFE);
            }
            catch (MembershipCreateUserException MCUE)
            {
                Oplaco.Exceptions.AppService.ProcessAndNotifyBusinessLayerException(MCUE);
            }
            catch (Exception exception)
            {
                Oplaco.Exceptions.AppService.ProcessAndNotifyPresentationLayerException(exception);
            }
        }

        

        // <summary>
        /// ValidateUser: login process
        /// </summary>
        /// <param name="username">string username</param>
        /// <param name="password">string password</param>
        /// <returns>bool</returns>
        public bool ValidateUser(string username, string password)
        {
            bool validated = false;
            try
            {

                validated = Membership.ValidateUser(username, password);
            }
            catch (Oplaco.Exceptions.DataAccessLayerException DLE)
            {
                Oplaco.Exceptions.AppService.ReplaceWithPresentationLayerException(DLE);
            }
            catch (Exception exception)
            {
                Oplaco.Exceptions.AppService.ProcessAndNotifyPresentationLayerException(exception);
            }

            return validated;
        }

        /// <summary>
        /// Validate user: validates user based on twitter integration
        /// </summary>
        /// <param name="twitterUsername"></param>
        /// <returns></returns>
        public bool ValidateUser(string twitterUsername)
        {

            bool validated = false;
            try
            {
                this.Initialize(twitterUsername);
                if (!String.IsNullOrEmpty(this.TwitterSecret) && !String.IsNullOrEmpty(this.TwitterToken))
                {
                    
                    
                    validated = true;
                }
                
            }
            catch (Oplaco.Exceptions.DataAccessLayerException DLE)
            {
                Oplaco.Exceptions.AppService.ReplaceWithPresentationLayerException(DLE);
            }
            catch (Exception exception)
            {
                Oplaco.Exceptions.AppService.ProcessAndNotifyPresentationLayerException(exception);
            }

            return validated;
        }

        public string GetRandomPassword(int length)
        {
            // Get the GUID
            string guidResult = System.Guid.NewGuid().ToString();

            // Remove the hyphens
            guidResult = guidResult.Replace("-", string.Empty);

            // Make sure length is valid
            if (length <= 0 || length > guidResult.Length)
                throw new ArgumentException("Length must be between 1 and " + guidResult.Length);

            // Return the first length bytes
            return guidResult.Substring(0, length);
        }

        /*
        /// <summary>
        /// 
        /// </summary>
        /// <param name="Document"></param>
        /// <returns></returns>
        public XmlDocument CreateWindowsLiveList(XmlDocument Document)
        {
            //Create our XMLdocument
            XmlDocument FriendsList = new XmlDocument();
            //Create the rootnode(Friends) of the document 
            XmlElement RootNode = FriendsList.CreateElement("Friends");
            //Add our root to the document
            FriendsList.AppendChild(RootNode);

            try
            {
                //Create a node list starting by Contact
                XmlNodeList ContactList = Document.GetElementsByTagName("Contact");

                //Every node will be checked if it contains a name and an email. 
                foreach (XmlNode Node in ContactList)
                {
                    XmlElement ContactElement = (XmlElement)Node;
                    XmlElement FriendElement = FriendsList.CreateElement("Friend");
                    XmlElement NameElement = FriendsList.CreateElement("Name");
                    XmlElement EmailElement = FriendsList.CreateElement("Email");

                    if (ContactElement.GetElementsByTagName("Address")[0] != null)
                    {
                        EmailElement.InnerText = ContactElement.GetElementsByTagName("Address")[0].InnerText;
                    }

                    if (ContactElement.GetElementsByTagName("UniqueName")[0].InnerText != null)
                    {
                        NameElement.InnerText = ContactElement.GetElementsByTagName("UniqueName")[0].InnerText;
                    }

                    FriendElement.AppendChild(NameElement);
                    FriendElement.AppendChild(EmailElement);
                    RootNode.AppendChild(FriendElement);
                }

            }
            catch (Chefdog.Exceptions.DataAccessLayerException DLE)
            {
                Chefdog.Exceptions.AppService.ReplaceWithPresentationLayerException(DLE);
            }
            catch (Exception exception)
            {
                Chefdog.Exceptions.AppService.ProcessAndNotifyPresentationLayerException(exception);
            }

            return FriendsList;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Contacts"></param>
        /// <returns></returns>
        public XmlDocument CreateGmailList(ContactsRequest Contacts)
        {
            XmlDocument FriendList = new XmlDocument();
            XmlElement RootNode = FriendList.CreateElement("Friends");
            //Add our root to the document
            FriendList.AppendChild(RootNode);

            Feed<Contact> f = Contacts.GetContacts();
            foreach (Contact c in f.Entries)
            {
                XmlElement FriendElement = FriendList.CreateElement("Friend");
                XmlElement EmailElement = FriendList.CreateElement("Email");

                XmlElement NameElement = FriendList.CreateElement("Name");
                foreach (EMail mail in c.Emails)
                {
                    NameElement.InnerText = c.Title;
                    EmailElement.InnerText = mail.Address;
                }


                FriendElement.AppendChild(NameElement);
                FriendElement.AppendChild(EmailElement);

                RootNode.AppendChild(FriendElement);
            }
            return FriendList;
        }
        */
    }
}
